// This is the first part of the middlewares that try to work out the contract
// the reason is, it will get re-use by subsequences middlewares
// so we might as well do this here
// Also we could hijack it off and serve the html files up for documentation purpose
import { CONTRACT_NAME } from 'jsonql-constants'
import {
  getContract,
  handleContract,
  contractAuth
} from '../contracts'
import {
  getDebug,
  ctxErrorHandler
} from '../utils'

const debug = getDebug('contract-middleware')

/**
 * @TODO is there a bug in here somewhere that I am not aware of
 * it seems to me that everytime the middleware get call, it keep trying to
 * generate contract, or reading from the contract, which is not ideal
 * it should able to cache it some how?
 */
export default function contractMiddleware(opts) {
  // export
  return async function(ctx, next) {
    // this will only handle certain methods
    const { isReq, resolverType } = ctx.state.jsonql;
    // @2019-05-24 We need to make sure the call is actually a jsonql call
    // because when http access happen it could make multiple call to the
    // server and contract generator just run multiple times on a very short time
    // and cause the file read failure
    if (isReq) {
      // now is this request asking for the public contract
      if (resolverType === CONTRACT_NAME) {
        if (contractAuth(ctx, opts)) {
          let publicContractJson = ctx.state.jsonql.publicContract;
          if (!publicContractJson) {
            debug(`call the get public contract here`, opts.name)
            // This should be a one off event
            publicContractJson = await getContract(opts, true)
            ctx.state.jsonql.publicContract = publicContractJson;
          }
          // debug('call handle public contract method here');
          // this is a public contract
          return handleContract(opts, ctx, publicContractJson)
        } else {
          return ctxErrorHandler(ctx, 'JsonqlContractAuthError')
        }
      }
    }
    await next()
  }
}
